import 'dart:math';

import 'package:acgn_pioneer/widgets/reader/events/_index.dart';
import 'package:acgn_pioneer/widgets/reader/mixins/_index.dart';
import 'package:flutter/material.dart';

import '../../../../public.dart';
import 'barrage_controller.dart';
import 'barrage_item.dart';
import 'barrage_transition_item.dart';

/// 弹幕主体
class ReaderBarrageMain extends StatefulWidget {
  final int chapterId; //章节id
  final int index; // 图片序号
  final double height; // 图片高度

  ReaderBarrageMain({Key key, this.chapterId, this.index, this.height})
      : super(key: key);

  @override
  State<StatefulWidget> createState() => ReaderBarrageMainState();
}

class ReaderBarrageMainState extends State<ReaderBarrageMain>
    with ReaderWidgetBase {
  Random random = Random();
  bool isRefreshing = false;
  // 每一张的通道是单独的，从基础BarrageState中拷贝一份
  List<BarrageWidgetChannel> perBarrageChannels = [];
  List<Widget> barrageWidgets = [];

  // 弹幕实体(读取改章节的数据显示)
  List<ChapterBarrageModel> get barrageModels {
    return readerPage.barrageController.barrageModels
        .where((e) =>
            e.chapterId == widget.chapterId && e.imageIndex == widget.index)
        .toList();
  }

  // 弹幕控制器
  BarrageController get barrageController {
    return readerPage.barrageController;
  }

  // 弹幕设置
  BarrageSetting get barrageSetting {
    return readerPage.barrageController.barrageSetting;
  }

  @override
  void initState() {
    super.initState();

    initChannels();

    readerPage.bus.on<ReaderChapterImageIndexChangeEvent>().listen((event) {
      if (event.img.chapterId != widget.chapterId ||
          event.img.index != widget.index) {
        return;
      }
      refreshBarrage();
    });

    readerPage.bus.on<ReaderCommentChangeSpeedEvent>().listen((event) {
      barrageSetting.speed = event.speed;
    });

    barrageController.addListener(() {
      refreshBarrage();
    });

    refreshBarrage();
  }

  @override
  Widget build(BuildContext context) {
    return Stack(children: barrageWidgets);
  }

  @override
  void dispose() {
    super.dispose();
  }

  // 刷新弹幕
  refreshBarrage() {
    if (isRefreshing || !mounted) {
      return;
    }
    isRefreshing = true;
    List<BarrageWidgetChannel> channels = getFreeBarrageChannels();
    var list =
        barrageModels.where((c) => !c.isShowing).take(channels.length).toList();
    for (int i = 0; i < list.length; i++) {
      int channelNum = channels[i].channelNum;
      double offsetTop = getOffset(channelNum);
      var tempModel = list[i];
      var tempChannel = channels[i];
      var tempWidget;
      tempModel.isShowing = true;
      tempChannel.status = 1;
      tempWidget = BarrageTransitionItem(
        key: UniqueKey(),
        channel: channels[i],
        child: BarrageItem.textItem(tempModel.text),
        postionTop: offsetTop,
        visible: () {
          tempChannel.status = 0;
          refreshBarrage();
        },
        complete: () {
          finishAnimation(tempModel, tempWidget);
        },
        dispose: () {
          // 非正常回收
          tempChannel.status = 0;
          tempModel.isShowing = false;
          barrageWidgets.remove(tempWidget);
        },
      );
      barrageWidgets.add(tempWidget);
    }
    isRefreshing = false;
    setState(() {});
  }

  // 动画完成
  finishAnimation(ChapterBarrageModel model, Widget widget) {
    model.isShowing = false;
    model.showCount += 1;
    barrageWidgets.remove(widget);
    refreshBarrage();
  }

  // 弹幕通道生成
  initChannels() {
    var channelCount = (widget.height - barrageSetting.safeTopHeight) ~/
        (barrageSetting.channelPadding + barrageSetting.channelHeight);

    channelCount = min(channelCount, barrageSetting.maxChannelCount);
    for (int i = 0; i < channelCount; i++) {
      perBarrageChannels.add(BarrageWidgetChannel(i, random.nextInt(1000)));
    }
  }

  // 获取空闲的通道
  List<BarrageWidgetChannel> getFreeBarrageChannels() {
    return perBarrageChannels.where((item) => item.status == 0).toList();
  }

  // 获取弹幕位置
  double getOffset(int channelNum) {
    return barrageSetting.safeTopHeight +
        (barrageSetting.channelHeight + barrageSetting.channelPadding) *
            channelNum;
  }
}
